import cv2
import dlib
import numpy as np
from matplotlib.path import Path
import time
import math

def shape_to_np(shape, dtype='int'):
    coords = np.zeros((68, 2), dtype=dtype)
    for i in range(0, 68):
        coords[i] = (shape.part(i).x, shape.part(i).y)
    return coords


def ROI(file, predictor):
    img = cv2.imread('../data/TMP2/%s' % file)
    # img = cv2.imread('../data/TMP/%s' % file)
    # conver to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    detector = dlib.get_frontal_face_detector()

    # rects contains all the faces detected
    rects = detector(gray, 1)
    shape = predictor(gray, rects[0])
    shape = shape_to_np(shape)
    forehead = np.zeros((4, 2), np.int32)
    cheeks_L = np.zeros((4, 2), np.int32)
    cheeks_R = np.zeros((4, 2), np.int32)

    for itm in shape:
        cv2.circle(img, itm, 2, (0, 0, 255), -1)

    # 区域定位
    cheeks_L[0] = shape[0] + (10, 2)
    cheeks_L[1] = cheeks_L[0] + (33, 2)
    cheeks_L[2] = cheeks_L[1] + (-12, 50)
    cheeks_L[3] = cheeks_L[2] - (14, 13)
    #
    cheeks_R[0] = shape[16] + (-9, 5)
    cheeks_R[1] = cheeks_R[0] + (-33, 4)
    cheeks_R[2] = cheeks_R[1] + (16, 52)
    cheeks_R[3] = cheeks_R[2] + (14, -13)
    #
    delt_x, delt_y = abs(shape[18] - shape[25])
    forehead[0] = shape[18] - (0, 5)
    forehead[1] = forehead[0] + (0.35 * delt_x / np.tan(np.radians(80)), -0.35*delt_x)
    forehead[3] = shape[25] - (0, 5)
    forehead[2] = forehead[3] - (0.35 * delt_x / np.tan(np.radians(78)), 0.35*delt_x)
    # 脸颊左
    # cv2.polylines(img, [cheeks_L], True, (255, 0, 255))

    # 脸颊右
    # cv2.polylines(img, [cheeks_R], True, (255, 255, 0))

    # 额头
    cv2.polylines(img, [forehead], True, (0, 255, 255))
    # w1 = forehead[3][0] - forehead[0][0]
    # h1 = h2 = 20
    # forehead[1][0] = forehead[0][0] + 0.05 * w1
    # forehead[1][1] = forehead[0][1] - 1.7 * h1
    # forehead[0][1] -= 7
    # w2 = 0.75 * w1
    # forehead[2][0] = forehead[1][0] + w2
    # forehead[2][1] = forehead[1][1] - 0.05 * h1
    # 画多个时打开这条语句
    # pts = pts.reshape((-1, 4, 2))
    # forehead 坐标 [[x1, y1 - 7], [x2, y2], [x4, y4], [x3, y3 - 8]]

    # 获取区域内所有的点
    path1 = Path(cheeks_L)
    path2 = Path(cheeks_R)
    path3 = Path(forehead)
    xMin1, yMin1, xMax1, yMax1 = np.asarray(path1.get_extents(), dtype=int).ravel()
    xMin2, yMin2, xMax2, yMax2 = np.asarray(path2.get_extents(), dtype=int).ravel()
    xMin3, yMin3, xMax3, yMax3 = np.asarray(path3.get_extents(), dtype=int).ravel()
    x1, y1 = np.mgrid[xMin1:xMax1, yMin1:yMax1]
    x2, y2 = np.mgrid[xMin2:xMax2, yMin2:yMax2]
    x3, y3 = np.mgrid[xMin3:xMax3, yMin3:yMax3]
    points1 = np.vstack((x1.ravel(), y1.ravel())).T
    points2 = np.vstack((x2.ravel(), y2.ravel())).T
    points3 = np.vstack((x3.ravel(), y3.ravel())).T
    mask1 = path1.contains_points(points1)
    mask2 = path2.contains_points(points2)
    mask3 = path3.contains_points(points3)
    path_points1 = points1[np.where(mask1)]
    path_points2 = points2[np.where(mask2)]
    path_points3 = points3[np.where(mask3)]
    for i in path_points1:
        cv2.circle(img, i, 2, (255, 178, 5), -1)
    for i in path_points2:
        cv2.circle(img, i, 2, (255, 178, 5), -1)
    # for i in path_points3:
    #     cv2.circle(img, i, 2, (255, 178, 5), -1)

    cv2.imshow('a', img)
    cv2.waitKey(0)
    return path_points1, path_points2, path_points3


if __name__ == '__main__':
    predictor = dlib.shape_predictor('../models/shape_predictor_68_face_landmarks.dat')
    ROI('2.png', predictor)


